// 初始化数据库文件
const fsPromises = require('fs').promises
const path = require('path')
const clc = require('cli-color')
const inquirer = require('inquirer')
const zipper = require('zip-local')
// 初始数据库
const initialDatabase = require('./initialDatabase')

const error = clc.red.bold
const warn = clc.yellow
const notice = clc.blue
const success = clc.green

// 数据库存储路径
const { dbDir } = require('../config/config.default')

// 生成数据库存储路径
async function makeDbDir () {
  try {
    await fsPromises.access(dbDir)
  } catch (error) {
    fsPromises.mkdir(dbDir)
  }
}

// 数据库文件生成器
async function dbFileGenerator (filename, data, reset = false) {
  data = typeof data !== 'string' ? JSON.stringify(data) : data
  const filepath = path.join(dbDir, filename + '.json')

  // 非强制重置命令
  if (!reset) {
    // 如果文件存在则跳过
    try {
      await fsPromises.access(filepath)
      console.log(success(`跳过 ${filename}.json`))
      return
    } catch (error) {}
  }

  fsPromises.writeFile(filepath, data)

  // 返回有值则表示重新生成了文件，否则表示未执行任何操作
  console.log(warn(`生成 ${filename}.json`))
  return 'ok'
}

// 获取交互选项
function getOpts () {
  return inquirer
    .prompt([
      {
        name: 'reset',
        type: 'list',
        message: '替换方式 ->',
        default: true,
        choices: [
          {
            name: '强制替换并初始化全部数据库文件',
            value: true
          },
          {
            name: '只初始化缺失的数据库文件',
            value: false
          }
        ]
      },
      {
        name: 'backup',
        type: 'confirm',
        message: '是否备份 ->',
        default: false
      }
    ])
}

// 备份数据库
function backupDatabase () {
  return zipper.sync.zip(dbDir).save(path.join(__dirname, `db-${Date.now()}.zip`))
}

async function begin () {
  const { reset, backup } = await getOpts()

  // 控制台任务标题
  const title = `初始化数据库${reset ? '(全部)' : ''}`

  console.log(notice(`\n====== ${title} start ======\n`))

  // 生成数据库存储路径
  await makeDbDir()

  // 备份数据库
  if (backup) {
    backupDatabase()
  }

  const dbGens = initialDatabase.map(({ name, data }) => dbFileGenerator(name, data, reset))
  const results = await Promise.allSettled(dbGens)

  const failArr = []
  results.forEach((v, i) => {
    if (v.status === 'rejected') {
      failArr.push({
        name: initialDatabase[i].name,
        reason: v.reason instanceof Error ? v.reason.message : v.reason
      })
    }
  })

  if (failArr.length > 0) {
    console.log(clc.columns([
      [error('失败的文件:')],
      [clc.bold('Name'), clc.bold('Reason')],
      ...failArr.map(v => Object.values(v))
    ]))
  }

  console.log(notice(`\n====== ${title}  end  ======`))
}

begin()
